package com.wnxy.sdd.log;
import java.util.Arrays;
import java.util.Date;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wnxy.sdd.entity.SysLog;
import com.wnxy.sdd.service.ISysLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 日志切面类，拦截自定义日志注解，用来实现日志的自动记录
 */
@Component
@Aspect
public class SysLogAspect {

    @Autowired
    private ISysLogService sysLogService;

    /**
     * @Around("@annotation(systemLog)") 环绕通知
     * 1、@annotation 表示拦截的是指定的注解
     * 2、systemLog 对应的是方法形参名称
     */
    @Around("@annotation(systemLog)")
    public Object insertLog(ProceedingJoinPoint pjp,SystemLog systemLog){
        try {
            // 执行目标对象的方法 (注解写到controller上，所以这里的返回值对象是：Result)
            Object retValue = pjp.proceed();
            // 正常执行方法之后，记录日志
            saveLog(pjp,systemLog,retValue);
            return retValue;
        } catch (Throwable e) {
            // TODO 错误日志需要根据系统规范处理
            throw new RuntimeException(e);
        }
    }

    /**
     * 保存日志到sdd_log表中
     * @param pjp
     * @param systemLog
     */
    private void saveLog(ProceedingJoinPoint pjp, SystemLog systemLog, Object retValue) throws JsonProcessingException {
        // 获取request对象
        HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();

        SysLog sysLog = new SysLog();
        // 请求方式: request.getMethod();
        sysLog.setReqType(request.getMethod());
        // 请求IP： request.getRemoteAddress();
        sysLog.setIp(request.getRemoteAddr());
        // 请求地址：request.getUrl();
        // url:统一资源定位符； http://localhost:8080/getById
        // uri:统一资源标识符： /getById
        sysLog.setReqUrl(request.getRequestURL().toString());
        // 设置请求参数: 数组-->String
        sysLog.setReqParams(Arrays.toString(pjp.getArgs()));
        // 设置返回数据：如Result对象
        // 对象-->Json
        ObjectMapper objectMapper = new ObjectMapper();
        String str = objectMapper.writeValueAsString(retValue);
        sysLog.setRespData(str);
        // 设置类全名
        sysLog.setFullClass(pjp.getTarget().getClass().getName());
        // 设置当前执行的方法名；（方法签名）
        sysLog.setMethod(pjp.getSignature().getName());
        sysLog.setOperateTime(new Date());
        // 操作类型：获取的是枚举类型, 通过ordinal()方法获取枚举对象的索引
        sysLog.setOptType(systemLog.type().ordinal());
        sysLog.setTitle(systemLog.value());
        // 保存日志
        sysLogService.save(sysLog);
    }
}
